package edu.gatech.cs4400.spring2014.A8.model;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import edu.gatech.cs4400.spring2014.A8.control.Session;

/**
 * Class responsible for the loading, storing, and saving of patient profile information
 * 
 * @author Stephen
 */
public class PatientProfileData {
	private String name;
	private String homePhone;
	private int annualIncome;
	private Date dateOfBirth;
	private String gender;
	private String address;
	private String workPhone;
	private int weight;
	private float height;
	private String contactName;
	private String contactPhone;
	private ArrayList<String> allergies;
	
	private boolean loaded;
	private boolean hasData;
	
	/**
	 * Constructor
	 */
	public PatientProfileData() {
		loaded = false; 
		hasData = false;
	}
	
	/**
	 * Load the profile from the database
	 * @return success of load 
	 */
	public boolean loadData() {
		if (!loaded) {
			LoadPatientDataQuery lpdq = new LoadPatientDataQuery();
			lpdq.loadData();
			LoadAllergyDataQuery ladq = new LoadAllergyDataQuery();
			ladq.loadData();
			loaded = true;
		}
		else {
			System.out.println("Already loaded patient profile");
		}
		return hasData;
	}
	
	public boolean saveData() {
		SavePatientDataQuery spdq = new SavePatientDataQuery();
		SaveAllergyDataQuery sadq = new SaveAllergyDataQuery();
		spdq.saveProfile();
		sadq.saveAllergies();
		return true;
	}
	
	/**
	 * Determine if the class has any useful data
	 * @return true if loaded data, false if not loaded or if no data existed
	 */
	public boolean hasData() {
		return hasData;
	}
	
	/**
	 * Print all data fields out
	 */
	public String toString() {
		return String.format("Profile data: %s %s %d %s %s %s %s %d %f\n", name, homePhone, annualIncome, dateOfBirth, gender, address, workPhone, weight, height);
	}
	
	/**
	 * If the given string is null, give back the empty string
	 * @param text
	 * @return
	 */
	private String nullCheck(String text) {
		if (text == null) {
			return "";
		}
		return text;
	}
	
	/**
	 * Getter methods for all data fields. 
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<String> getAllergies() { if(allergies != null) return (ArrayList<String>)allergies.clone(); return new ArrayList<String>();}
	public String getName() 				{ return nullCheck(name);}
	public String getHomePhone() 			{ return nullCheck(homePhone);}
	public int getAnnualIncome() 			{ return annualIncome;}
	public Date getDateOfBirth() 			{ if (dateOfBirth != null) return (Date)dateOfBirth.clone(); return null;}
	public String getGender() 				{ return nullCheck(gender);}
	public String getAddress() 				{ return nullCheck(address);}
	public String getWorkPhone() 			{ return nullCheck(workPhone);}
	public int getWeight() 					{ return weight;}
	public float getHeight() 				{ return height;}
	public String getContactName()			{ return nullCheck(contactName);}
	public String getContactPhone()		{ return nullCheck(contactPhone);}

	public boolean setAllergies(ArrayList<String> newAllergies) {
		allergies = newAllergies;
		return true;
	}
	
	public boolean setName(String newName) {
		name = newName;
		return true;
	}
	
	public boolean setContactName(String data) {
		contactName = data;
		return true;
	}
	
	public boolean setContactPhone(String data) {
		boolean result = false;
		if (data == "") {
			result = true;
		}
		else {
			String res = DataCleaner.phoneNumber(data);
			if (res != "") {
				result = true;
				contactPhone = res;
			}
		}
		return result;
	}
	
	public boolean setHomePhone(String newHomePhone) {
		boolean result = false;
		if (newHomePhone == "") {
			result = true;
		}
		else {
			String res = DataCleaner.phoneNumber(newHomePhone);
			if (res != "") {
				result = true;
				homePhone = res;
			}
		}
		return result;
	}
	
	public boolean setWorkPhone(String newWorkPhone) {
		boolean result = false;
		if (newWorkPhone == "") {
			result = true;
		}
		else {
			String res = DataCleaner.phoneNumber(newWorkPhone);
			if (res != "") {
				result = true;
				workPhone = res;
			}
		}
		return result;
	}

	public boolean setDateOfBirth(String birthday) {
		Date date = DataCleaner.date(birthday);
		if (date == null) {
			return false;
		}
		dateOfBirth = date;
		return true;
	}
	
	public boolean setGender(String newGender) {
		if (newGender.equals("M") || newGender.equals("F")) {
			gender = newGender;
			return true;
		}
		return false;
	}
	
	public boolean setAddress(String newAddress) {
		address = newAddress;
		return true;
	}
	
	public boolean setAnnualIncome(String data) {
		annualIncome = DataCleaner.nonnegativeInt(data);
		return true;
	}
	
	public boolean setWeight(String data) {
		weight = DataCleaner.nonnegativeInt(data);
		return true;
	}
	
	public boolean setHeight(String data) {
		height = DataCleaner.nonnegativeFloat(data);
		return true;
	}
	
	
	/**
	 * Wrapper class for a query that retrieves the patient's profile information from the databse
	 * 
	 * @author Stephen
	 */
	private class LoadPatientDataQuery extends ReadQuery {
		
		public LoadPatientDataQuery() {
			sql = String.format("SELECT Name, HomePhone, AnnualIncome, DateOfBirth, Gender, Address, WorkPhone, Weight, Height, ContactName, ContactPhone " +
						        "FROM Patient " +
					 			"WHERE Username = '%s';", Session.getUsername());
		}
		
		/**
		 * Extract the data from the first row of the result.
		 */
		@Override
		protected void parseResult(ResultSet rs) throws SQLException {
			if (rs.next()) {
				name = rs.getString("Name");
				homePhone = rs.getString("HomePhone");
				annualIncome = rs.getInt("AnnualIncome");
				dateOfBirth = rs.getDate("DateOfBirth");
				gender = rs.getString("Gender");
				address = rs.getString("Address");
				workPhone = rs.getString("WorkPhone");
				weight = rs.getInt("Weight");
				height = rs.getFloat("Height");
				contactName = rs.getString("ContactName");
				contactPhone = rs.getString("ContactPhone");
				
				hasData = true;
			}
		}
		
		/**
		 * Load the data from the database
		 */
		public void loadData() {
			execute();
		}
	}
	
	/**
	 * Wrapper class for a query that loads the patient's allergy information from the database
	 * 
	 * @author Stephen
	 *
	 */
	private class LoadAllergyDataQuery extends ReadQuery {
		
		/**
		 * Constructor
		 */
		public LoadAllergyDataQuery() {
			sql = String.format("SELECT AllergyName FROM Allergies WHERE Patient_Username = '%s';", Session.getUsername());
		}
		
		/**
		 * Record each entry in the result table as a new allergy
		 */
		@Override
		protected void parseResult(ResultSet rs) throws SQLException {
			allergies = new ArrayList<String>();
			while (rs.next()) {
				allergies.add(rs.getString("AllergyName"));
			}			
		}
		
		/**
		 * Get the allergy data from the database
		 */
		public void loadData() {
			execute();
		}
	}
	
	private class SavePatientDataQuery extends WriteQuery {
		public SavePatientDataQuery() {
			if (hasData) {
				sql = String.format("UPDATE Patient " +
									"SET Name='%s', HomePhone='%s', AnnualIncome='%d', " +
										 "DateOfBirth='%s', Gender='%s', Address='%s', " +
										 "WorkPhone='%s', Weight='%d', Height='%.1f', " +
										 " ContactPhone='%s', ContactName='%s' " +
										 "WHERE Username='%s';", getName(), getHomePhone(),
										 getAnnualIncome(), getDateOfBirth(), getGender(), 
										 getAddress(), getWorkPhone(), getWeight(), getHeight(), 
										 getContactPhone(), getContactName(),
										 Session.getUsername());
				System.out.println(sql);
			}
			else {
				sql = String.format("INSERT INTO Patient(Username, Name, HomePhone, " +
								    	"AnnualIncome, DateOfBirth, Gender, Address, " +
								    	"WorkPhone, Weight, Height, ContactName, ContactPhone) " +
								    "VALUES('%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%d', '%.1f', '%s', '%s');", 
								    Session.getUsername(), getName(), getHomePhone(), getAnnualIncome(),
								    getDateOfBirth(), getGender(), getAddress(), getWorkPhone(), getWeight(), 
								    getHeight(), getContactName(), getContactPhone());
				
			}
		}
		
		public boolean saveProfile() {
			return execute();
		}
	}
	
	private class SaveAllergyDataQuery extends WriteQuery {
		
		public boolean saveAllergies() {
			sql = String.format("DELETE FROM Allergies WHERE Patient_Username ='%s';", Session.getUsername());
			execute();
			reset();
			if (allergies != null) {
				for (String allergy : allergies) {
					sql = String.format("INSERT INTO Allergies(Patient_Username, AllergyName) VALUES('%s', '%s');", Session.getUsername(), allergy);
					execute();
					reset();
				}
			}
			return true;
		}
	}
}
